Reflected XSS into a JavaScript string with angle brackets HTML encoded
Bypass de codificación HTML en un contexto JavaScript: dentro de una string, cerrar la comilla simple y comentar el resto ejecuta alert(1) sin necesidad de angle brackets.
Target Overview & Vulnerability Summary
El laboratorio contexts/lab-javascript-string-angle-brackets-html-encoded contiene un XSS reflejado en el tracking de consultas de búsqueda. Los angle brackets (<, >) se codifican como HTML, pero la reflexión ocurre dentro de una string JavaScript: el contexto correcto de escape es la comilla simple y el comentario, no el markup.
| Campo | Valor |
|---|---|
| Severidad | Media-Alta (ejecución de JavaScript en el contexto de la víctima) |
| Endpoint vulnerable | / (parámetro search) |
| Root cause | Reflexión del input dentro de una string JavaScript con solo HTML-encoding de angle brackets (escapado del contexto equivocado) |
Technical Breakdown & Exploitation Flow
1. Confirmación del contexto de reflexión
GET /?search=test HTTP/2
Host: <LAB-ID>.web-security-academy.net
La respuesta refleja el input dentro de una string delimitada por comillas simples:
<h1>0 search results for 'test'</h1>
2. Payload de break out de la string
GET /?search=';alert(1)// HTTP/2
Host: <LAB-ID>.web-security-academy.net
';— cierra la string JavaScript.alert(1)— expresión a ejecutar.//— comenta el resto de la línea, neutralizando el cierre de string y el código posterior.
Respuesta reflejada:
<h1>0 search results for '';alert(1)//'</h1>
Al cargarse la página, el JavaScript interpola ';alert(1)// rompiendo la string: el cierre de comilla del template queda comentado y alert(1) se ejecuta.
Root Cause Analysis
La codificación HTML de angle brackets (< → <, > → >) es una mitigación correcta para contextos de markup, pero insuficiente cuando la reflexión ocurre dentro de una string JavaScript. El HTML-encoding impide inyectar tags, no impide romper la string: en contexto JS el carácter peligroso es la comilla (y en menor medida backslash), no los brackets. La defensa aplicada no se corresponde con el contexto de salida — un clásico flaw de "escapado al contexto equivocado".
La reflectXSS en JS string requiere, al menos, escapar ', ", \ y caracteres de control (\x3c etc.), o usar serialización segura.
Secure Remediation
- Aplicar escaping al contexto JavaScript (no HTML): escapar comillas simples, comillas dobles, backslash y terminadores de línea antes de incrustar el valor en la string:
const safeSearch = search.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
- Mejor práctica: no interpolar datos del usuario en JavaScript inline. Enviar el valor como dato en un atributo
data-*JSON-serializado o viajar en una respuesta JSON consumida por el frontend. - Definir una política de codificación por contexto (HTML, attribute, JS, URL, CSS) en el framework de templates, en lugar de una única codificación global.